// 测试 < T extends Animal >

class Animal{
    // 在构造函数的参数中使用 访问修饰符 修饰参数
    // 会自动在本类中定义与参数名称同名的 属性
    // 同时相当于在构造函数内部完成了 this.type = type 操作
    constructor( public type:string ){
    }
    eat( food: string ){
        console.log( `${this.toString()}吃${food}` );
    }
    // 重写(或覆盖)从 Objecdt类 继承的 toString
    toString(): string{
        return `${this.type}类动物`;
    }
}

class Beast extends Animal {
    constructor( public name: string ){
        super( '兽' );
    }
    // 重写(或覆盖)从 Animal 类继承的 toString
    toString(): string{
        return `${this.type}类动物${this.name}`;
    }
}

class Bear extends Beast {
    constructor( name: string , public age: number ){
        super(name)
    }
    // 重写(或覆盖)从 Beast 类继承的 toString
    toString(): string{
        return `${this.type}类动物${this.name}(${this.age}岁)`;
    }
}

function feed<T extends Animal>( animal: T , food: string ) {
    animal.eat( food );
}

let birds = new Animal( '禽' );
feed<Animal>( birds , '玉米' );

let wolf = new Beast( '狼' );
//feed<Bear>( wolf , '猪后腿' );
feed<Beast>( wolf , '牛前腿' );

let bear = new Bear( '熊二' , 8 );
feed<Bear>( bear , '光头强' );